home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / awe2-0_1.lha / awe2-0.1 / Src / RCS / CpuMultiplexor.cc,v < prev    next >
Text File  |  1989-03-22  |  20KB  |  949 lines

  1. head     3.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    grunwald:3.2; strict;
  6. comment  @@;
  7.  
  8.  
  9. 3.2
  10. date     89.02.20.15.33.56;  author grunwald;  state Exp;
  11. branches ;
  12. next     3.1;
  13.  
  14. 3.1
  15. date     88.12.20.13.48.34;  author grunwald;  state Exp;
  16. branches ;
  17. next     1.2;
  18.  
  19. 1.2
  20. date     88.11.02.13.39.56;  author grunwald;  state Exp;
  21. branches ;
  22. next     1.1;
  23.  
  24. 1.1
  25. date     88.10.30.13.03.05;  author grunwald;  state Exp;
  26. branches ;
  27. next     ;
  28.  
  29.  
  30. desc
  31. @@
  32.  
  33.  
  34. 3.2
  35. log
  36. @Start using Gnu library heaps for schedulers
  37. @
  38. text
  39. @// This may look like C code, but it is really -*- C++ -*-
  40. // 
  41. // Copyright (C) 1988 University of Illinois, Urbana, Illinois
  42. //
  43. // written by Dirk Grunwald (grunwald@@cs.uiuc.edu)
  44. //
  45. #include "CpuMultiplexor.h"
  46. #include "SpinLock.h"
  47. #include "SpinFetchAndOp.h"
  48. #include "Thread.h"
  49. #include "ThreadContainer.h"
  50. #include "ReserveByException.h"
  51. #include <math.h>
  52.  
  53. //
  54. //    Things left to do:
  55. //
  56. //    + Make the ThreadHeap really use the Gnu PairingHeap structure.
  57. //      Doug Lea added an iterator class & other enhancements.
  58. //
  59. //    + Capture signals, transfer them to an Exception class. Can
  60. //      use this to implement time-slices & the like, as well as....
  61. //
  62. //    + Put in *addCpu* and *removeCpu* calls to CpuMultiplexor.
  63. //      This would allow run-time addition/removal of CPUS, so
  64. //      you can tailor your program to system 
  65. //        This is tricky. Should probably do it when you
  66. //        advance the clock, but it'll be tricky to get all
  67. //        the CPUs to agree on the barrier height for the
  68. //        rendezvous. Also might complicate the *distinct
  69. //        pools of threads per cpu*.
  70. //
  71.  
  72. int CpuMultiplexors;
  73. CpuMultiplexor *ThisCpu;
  74.  
  75. static SpinLock CpuMultiplexorsLock;
  76.  
  77. static int StopCpuMux;
  78.  
  79. SpinLock CpuCerrLock;
  80.  
  81. static SpinFetchAndOp GlobalCurrentEventsCounter(0);
  82. static SpinLock GivingUpLock;
  83. static int GivingUpCounter = 0;
  84. static int GivingUpGeneration = 0;
  85.  
  86. //
  87. //    A currentEvents pile for each processor. The count is only correct
  88. //    if youve reserved the spin lock -- its used as a guess.
  89. //
  90. static SpinLock CurrentEventsLock[MaxCpuMultiplexors];
  91. static int CurrentEventsCounter[MaxCpuMultiplexors];
  92. static ThreadContainer *CurrentEvents[MaxCpuMultiplexors];
  93.  
  94. //
  95. //    This can not be private, or we wont see all the action
  96. //
  97.  
  98. int CpuMuxDebugFlag = 0;
  99.  
  100. CpuMultiplexor::CpuMultiplexor(int debug) : systemContext(0, 0)
  101. {
  102.     pNameTemplate = "CpuMux";
  103.     currentThread = 0;
  104.     iYam = 0;
  105.     pid = 0;
  106.     CpuMuxDebugFlag = debug;
  107.     ThisCpu = this;
  108.     terminated = &StopCpuMux;
  109.     sprintf(nameSpace, "[%s-%d] ", pNameTemplate, iYam);
  110.     pName = nameSpace;
  111.  
  112.     allocateLocalEventStructures(0,1);
  113. }
  114.  
  115. CpuMultiplexor::~CpuMultiplexor()
  116. {
  117. }
  118.  
  119. void
  120. CpuMultiplexor::debug(int newdebug)
  121. {
  122.     CpuMuxDebugFlag = newdebug;
  123. }
  124.  
  125. int
  126. CpuMultiplexor::debug()
  127. {
  128.     return(CpuMuxDebugFlag);
  129. }
  130.  
  131. void
  132. CpuMultiplexor::terminateAll()
  133. {
  134.     StopCpuMux = 1;
  135. }
  136.  
  137. //
  138. // Add a single CPU to a set of current CPUs. There is an advantage of
  139. // having all child processes be spawned by CPU #0; all child signals
  140. // will be caught by the single parent.
  141. //
  142. // This entry is called by a Thread.
  143. //
  144. void CpuMultiplexor::enrollCpu()
  145. {
  146.     //
  147.     // move thread to master process. There's a distinct possibility
  148.     // that this guy will get stolen from Cpu #0 if everyone else is
  149.     // looking for work.
  150.     //
  151.     while (iYam != 0) {
  152.     currentThread -> cpuAffinity = 0;
  153.     rescheduleException.cpu(0);
  154.     raise( &rescheduleException );
  155.     }
  156.     //
  157.     // If we're only using a single 
  158.     //
  159.     //
  160.     // raise an exception to do the actual fork. This means that
  161.     // control flow for the new child process will be in the
  162.     // stirItAround loop, as opposed to here.
  163.     //
  164.     enrollDismissCpuException.enroll();
  165.     raise( &enrollDismissCpuException );
  166.     currentThread -> cpuAffinity = -1;
  167. }
  168.  
  169. void
  170. CpuMultiplexor::dismissCpu()
  171. {
  172.     assert(0);
  173. }
  174.  
  175. void
  176. CpuMultiplexor::allocateLocalEventStructures(int newIYam, int outOf)
  177. {
  178. #ifndef NDEBUG
  179.     if (CpuMuxDebugFlag) {
  180.     CpuCerrLock.reserve();
  181.     cerr << name() << "Allocate CpuMux structures for " << newIYam << "\n";
  182.     CpuCerrLock.release();
  183.     }
  184. #endif /* NDEBUG */
  185.  
  186.     iYam = newIYam;
  187.     sprintf(nameSpace, "[%s-%d] ", pNameTemplate, iYam);
  188.     pName = nameSpace;
  189.  
  190.     globalCurrentEventsCounter = &GlobalCurrentEventsCounter;
  191.  
  192.     CurrentEventsCounter[iYam] = 0;
  193.     CurrentEvents[iYam] = AllocateHardwareCurrentEventsStructure();
  194.  
  195.     myCurrentEvents = CurrentEvents[iYam];
  196.     myCurrentEventsLock = &CurrentEventsLock[iYam];
  197.     myCurrentEventsCounter = &CurrentEventsCounter[iYam];
  198.  
  199. #ifndef NDEBUG
  200.     if (CpuMuxDebugFlag) {
  201.     CpuCerrLock.reserve();
  202.     cerr << name() << "set CpuMultiplexors to " << outOf << "\n";
  203.     CpuCerrLock.release();
  204.     }
  205. #endif /* NDEBUG */
  206.  
  207.     CpuMultiplexorsLock.reserve();
  208.     CpuMultiplexors = outOf;
  209.  
  210.     GivingUpLock.reserve();
  211.     if (GivingUpCounter >= CpuMultiplexors) {
  212.     GivingUpGeneration++;
  213.     GivingUpCounter = 0;
  214.     }
  215.     GivingUpLock.release();
  216.  
  217.     CpuMultiplexorsLock.release();
  218. }
  219.  
  220. void
  221. CpuMultiplexor::allocateEventStructures(int newIYam, int outOf)
  222. {
  223.     allocateLocalEventStructures(newIYam, outOf);
  224. }
  225.  
  226. void
  227. CpuMultiplexor::deallocateEventStructures()
  228. {
  229. #ifndef NDEBUG
  230.     if (CpuMuxDebugFlag) {
  231.     CpuCerrLock.reserve();
  232.     cerr << name() << "Deallocate CpuMux structures for " << iYam << "\n";
  233.     CpuCerrLock.release();
  234.     }
  235. #endif /* NDEBUG */
  236.  
  237.     myCurrentEventsLock -> reserve();
  238.     //
  239.     // Move remaining events to another queue. We're not adding new events,
  240.     // just moving them around, so we don't increase GlobalCurrentEventsCounter
  241.     //
  242.     while ( CurrentEventsCounter[iYam] > 0 ) {
  243.     CurrentEventsLock[0].reserve();
  244.     assert(CurrentEvents[0] != 0);
  245.     while( ! myCurrentEvents -> isEmpty() )  {
  246.         CurrentEvents[0] -> add( myCurrentEvents -> remove() );
  247.         CurrentEventsCounter[0]++;
  248.         CurrentEventsCounter[iYam]--;
  249.     }
  250.     CurrentEventsLock[0].release();
  251.     }
  252.  
  253.     CpuMultiplexorsLock.reserve();
  254.     CpuMultiplexors--;
  255.  
  256.     GivingUpLock.reserve();
  257.     if (GivingUpCounter >= CpuMultiplexors) {
  258.     GivingUpGeneration++;
  259.     GivingUpCounter = 0;
  260.     }
  261.     GivingUpLock.release();
  262.  
  263.     CpuMultiplexorsLock.release();
  264.  
  265. #ifndef NDEBUG
  266.     if (CpuMuxDebugFlag) {
  267.     CpuCerrLock.reserve();
  268.     cerr << name() << "set CpuMultiplexors to " << CpuMultiplexors;
  269.     cerr << " and trigger GivingUp\n";
  270.     CpuCerrLock.release();
  271.     }
  272. #endif /* NDEBUG */
  273.  
  274.     delete myCurrentEvents;
  275.     myCurrentEvents = 0;
  276.     CurrentEvents[iYam] = 0;
  277.     CurrentEventsCounter[iYam] = 0;
  278.     myCurrentEventsLock -> release();
  279. }
  280.  
  281. void
  282. CpuMultiplexor::fireItUp(int cpus, unsigned shared)
  283. {
  284.     assert(cpus > 0);
  285.     
  286.     if ( cpus > MaxCpuMultiplexors ) {
  287.     cpus = MaxCpuMultiplexors;
  288.     }
  289.  
  290. #ifndef NDEBUG
  291.     if (CpuMuxDebugFlag) {
  292.     CpuCerrLock.reserve();
  293.     cerr << name() << "Allocate " << shared << " bytes of shared memory\n";
  294.     CpuCerrLock.release();
  295.     }
  296. #endif /* NDEBUG */
  297.  
  298.     if ( cpus > 1 ) {
  299.     extern void SharedMemoryInit( unsigned );
  300.     SharedMemoryInit( shared );
  301.     }
  302.  
  303.     warmThePot(cpus);
  304.     stirItAround();
  305.     coolItDown();
  306. }
  307.  
  308. void
  309. CpuMultiplexor::warmThePot(int cpus)
  310. {
  311.     assert(cpus > 0);
  312.     
  313.     if ( cpus > MaxCpuMultiplexors ) {
  314.     cpus = MaxCpuMultiplexors;
  315.     }
  316.  
  317.     CpuMultiplexors = cpus;
  318.     enabled = 1;
  319.  
  320.     //
  321.     //    Spawn the children, giving each a unique number from 0..(cpus-1).
  322.     //  The first child gets id (cpus-1), and the original process gets 0.
  323.     //
  324.  
  325.     iYam = 0;
  326. #ifndef NDEBUG
  327.     if (CpuMuxDebugFlag) {
  328.     CpuCerrLock.reserve();
  329.     cerr << name() << "Allocate " << CpuMultiplexors << "cpus\n";
  330.     CpuCerrLock.release();
  331.     }
  332. #endif /* NDEBUG */
  333.  
  334.     
  335.     for (int whoAmI = 1; whoAmI < CpuMultiplexors; whoAmI++) {
  336.     if (iYam == 0) {
  337.         int pid = fork();
  338.         if (pid == 0) {    // child 
  339.         allocateEventStructures(whoAmI, CpuMultiplexors);
  340.         break;
  341.         }
  342.     }
  343.     }
  344.     pid = getpid();
  345. #ifndef NDEBUG
  346.     if (CpuMuxDebugFlag) {
  347.     CpuCerrLock.reserve();
  348.     cerr << name() << "I am now id " << iYam << " and pid " << pid <<" \n";
  349.     CpuCerrLock.release();
  350.     }
  351. #endif /* NDEBUG */
  352. }
  353.  
  354. void
  355. CpuMultiplexor::coolItDown()
  356. {
  357.     if (iYam > 0) {
  358. #ifndef NDEBUG
  359.     if (CpuMuxDebugFlag) {
  360.         CpuCerrLock.reserve();
  361.         cerr << name() << "exit\n";
  362.         CpuCerrLock.release();
  363.     }
  364. #endif
  365.     deallocateEventStructures();
  366.     _exit(0);
  367.     }
  368.     else {
  369.     //
  370.     //    reap the dead children. This way we know they are all dead.
  371.     //    The caller can then safely exit.
  372.     //
  373.     while (CpuMultiplexors > 1) {
  374.         int pid = wait(0);
  375.         if (pid == -1) {
  376.         perror("wait");
  377.         break;
  378.         }
  379.     }
  380.     //
  381.     //  In case of break in above loop
  382.     //
  383.     CpuMultiplexors = 1;
  384.     }
  385. }
  386.  
  387. void
  388. CpuMultiplexor::add(Thread *who)
  389. {
  390. #ifndef NDEBUG
  391.     if (CpuMuxDebugFlag) {
  392.     CpuCerrLock.reserve();
  393.     if (who != 0 && who -> name() != 0) {
  394.         cerr << name() << " add " << who -> name() << "\n";
  395.     } else {
  396.         cerr << name() << " add " << hex(long(who)) << "\n";
  397.     }
  398.     CpuCerrLock.release();
  399.     }
  400. #endif /* NDEBUG */
  401.     myCurrentEventsLock -> reserve();
  402.     addUnlocked( who );
  403.     (*myCurrentEventsCounter)++;
  404.     myCurrentEventsLock -> release();
  405.  
  406.     GlobalCurrentEventsCounter.add(1);
  407. }
  408.  
  409. void
  410. CpuMultiplexor::addToAnother(int cpu, Thread *who)
  411. {
  412.     assert( cpu >= 0 && cpu < CpuMultiplexors );
  413.     CurrentEventsLock[cpu].reserve();
  414.     CurrentEvents[cpu] -> add( who );
  415.     CurrentEventsCounter[cpu]++;
  416.     CurrentEventsLock[cpu].release();
  417.  
  418.     GlobalCurrentEventsCounter.add(1);
  419. }
  420.  
  421. Thread *
  422. CpuMultiplexor::remove()
  423. {
  424.     //
  425.     // Check to see if there is a current event, either in our current
  426.     // events queue or someone elses current events queue. If there is
  427.     // nothing, return 0.
  428.     //
  429.     
  430.     Thread *threadToExecute = 0;
  431.     
  432.     //
  433.     //    System stopped?
  434.     //
  435.     if (StopCpuMux) {
  436. #ifndef NDEBUG
  437.     if (CpuMuxDebugFlag) {
  438.         CpuCerrLock.reserve();
  439.         cerr << name() << " Stopping muxing \n" ;
  440.         CpuCerrLock.release();
  441.     }
  442. #endif /* NDEBUG */
  443.     return(0);
  444.     }
  445.     
  446.     //
  447.     //    I got something to do?
  448.     //
  449.     
  450.     myCurrentEventsLock -> reserve();
  451.     
  452.     if ( *myCurrentEventsCounter > 0 ) {
  453.     threadToExecute = myCurrentEvents -> remove();
  454.     (*myCurrentEventsCounter) --;
  455.     }
  456.     
  457.     myCurrentEventsLock -> release();
  458.     
  459.     //
  460.     //    Maybe someone else has something to do?
  461.     //
  462.     if ( threadToExecute == 0 && GlobalCurrentEventsCounter.value() > 0 ) {
  463.     int ask = iYam;
  464.     do {
  465.         ask++;                // start with next person,
  466.         if ( ask >= CpuMultiplexors ) {    // wrap around for fairness
  467.         ask = 0;
  468.         }
  469. #ifndef NDEBUG
  470.         if (CpuMuxDebugFlag) {
  471.         CpuCerrLock.reserve();
  472.         cerr << name() << "Ask " << ask << " about events \n";
  473.         CpuCerrLock.release();
  474.         }
  475. #endif /* NDEBUG */
  476.         //
  477.         // Note that were *not* locking before looking
  478.         // at CurrentEventsCount -- we treat this as a *guess*
  479.         // before bothering to lock on it. Admittedly, this could
  480.         // cause a problem, so maybe the second time around,
  481.         // we should always reserve and then look. 
  482.         //
  483.         if ( CurrentEventsCounter[ask] > 0) {
  484.         CurrentEventsLock[ask].reserve();
  485.         if ( CurrentEventsCounter[ask] > 0) {
  486. #ifndef NDEBUG
  487.             if (CpuMuxDebugFlag) {
  488.             CpuCerrLock.reserve();
  489.             cerr << name();
  490.             cerr << "Found one in " << ask << "\n";
  491.             CpuCerrLock.release();
  492.             }
  493. #endif /* NDEBUG */
  494.             threadToExecute = CurrentEvents[ask] -> remove();
  495.             //
  496.             // Check that this thread isnt trying to get to
  497.             // a specific CPU.
  498.             //
  499.             if (threadToExecute -> cpuAffinity > 0 &&
  500.             threadToExecute -> cpuAffinity != iYam) {
  501. #ifndef NDEBUG
  502.                 if (CpuMuxDebugFlag) {
  503.                 CpuCerrLock.reserve();
  504.                 cerr << name();
  505.                 cerr << "but returned it because of afinity\n";
  506.                 CpuCerrLock.release();
  507.                 }
  508. #endif /* NDEBUG */
  509.                 CurrentEvents[ask] -> add(threadToExecute);
  510.                 threadToExecute = 0;
  511.             }
  512.             else {
  513.             CurrentEventsCounter[ask]--;
  514.             }
  515.         }
  516.         CurrentEventsLock[ask].release();
  517.         }
  518.     } while (ask != iYam && threadToExecute == 0);
  519.     }
  520.     
  521. #ifndef NDEBUG
  522.     if (CpuMuxDebugFlag) {
  523.     CpuCerrLock.reserve();
  524.     cerr << name() << "find ";
  525.     if (threadToExecute == 0) {
  526.         cerr << "nothing\n";
  527.     } else {
  528.         cerr << threadToExecute -> name() << "\n";
  529.     }
  530.     CpuCerrLock.release();
  531.     }
  532. #endif /* NDEBUG */
  533.  
  534.     if ( threadToExecute != 0 ) {
  535.     GlobalCurrentEventsCounter.add(-1);
  536.     }
  537.     
  538.     return( threadToExecute );
  539. }
  540.  
  541. //
  542. //    Exception handlers
  543. //
  544. void
  545. CpuMultiplexor::raise(ExceptionClass *by)
  546. {
  547.     assert(currentThread != 0 && enabled);
  548.     raisedBy = by;
  549.     currentThread -> pContext.switchContext( &systemContext );
  550. }
  551.  
  552.  
  553. //
  554. // This is the job dispatcher.
  555. //
  556.  
  557. void
  558. CpuMultiplexor::stirItAround()
  559. {
  560.     currentThread = 0;
  561.  
  562.     if (!enabled) {
  563.     cerr << "Need to initialize CpuMultiplexor before using it\n";
  564.     }
  565.     
  566.     while( ! StopCpuMux ) {
  567.     while ( currentThread == 0 ) {
  568.         
  569.         currentThread = remove();
  570.         
  571.         if (currentThread != 0) {
  572.         break;
  573.         }
  574.         
  575.         GivingUpLock.reserve();
  576.         
  577.         GivingUpCounter++;
  578.         
  579.         assert( GivingUpCounter > 0 && GivingUpCounter <= CpuMultiplexors);
  580.         
  581.         if ( GivingUpCounter == CpuMultiplexors
  582.         && GlobalCurrentEventsCounter.value() == 0)
  583.         {
  584.         
  585.         GivingUpGeneration ++;
  586.         GivingUpCounter = 0;
  587.         GivingUpLock.release();
  588.         
  589. #ifndef NDEBUG
  590.             if (CpuMuxDebugFlag) {
  591.             CpuCerrLock.reserve();
  592.             cerr << name() << "give up\n";
  593.             CpuCerrLock.release();
  594.             }
  595. #endif /* NDEBUG */
  596.  
  597.         return;
  598.         }
  599.         else {
  600.         int generation = GivingUpGeneration;
  601.         
  602.         GivingUpLock.release();
  603.         
  604.         while( generation == GivingUpGeneration
  605.               && GlobalCurrentEventsCounter.value() == 0
  606.               && !StopCpuMux )
  607.         {
  608.             extern makeVolatile(void *);
  609.             makeVolatile(&generation);
  610.         }
  611.         
  612.         GivingUpLock.reserve();
  613.         if ( GivingUpGeneration != generation || StopCpuMux ) {
  614. #ifndef NDEBUG
  615.             if (CpuMuxDebugFlag) {
  616.             CpuCerrLock.reserve();
  617.             cerr << name() << " giving up\n";
  618.             CpuCerrLock.release();
  619.             }
  620. #endif /* NDEBUG */
  621.             GivingUpLock.release();
  622.             return;
  623.         }
  624.         else {
  625.             GivingUpCounter--;
  626.             assert(GivingUpCounter >= 0);
  627.             GivingUpLock.release();
  628. #ifndef NDEBUG
  629.             if (CpuMuxDebugFlag) {
  630.             CpuCerrLock.reserve();
  631.             cerr << name() << " check for something";
  632.             cerr << " i have " << *myCurrentEventsCounter;
  633.             cerr << " out of " ;
  634.             cerr << GlobalCurrentEventsCounter.value() << "\n";
  635.             CpuCerrLock.release();
  636.             }
  637. #endif /* NDEBUG */
  638.         }
  639.         }
  640.     }
  641.     
  642. #ifndef NDEBUG
  643.     if (CpuMuxDebugFlag || currentThread -> debug()) {
  644.         CpuCerrLock.reserve();
  645.         cerr << name() << " switch to ";
  646.         cerr << currentThread->name() << "\n";
  647.         CpuCerrLock.release();
  648.     }
  649. #endif /* NDEBUG */
  650.  
  651. #ifdef DEBUG_MALLOC
  652.     assert( malloc_verify() );
  653. #endif DEBUG_MALLOC
  654.     systemContext.switchContext(&(currentThread -> pContext));
  655. #ifdef DEBUG_MALLOC
  656.     assert( malloc_verify() );
  657. #endif DEBUG_MALLOC
  658.  
  659.     assert(raisedBy != 0);
  660.     raisedBy -> handleException();
  661.     raisedBy = 0;
  662.     }
  663. }
  664. @
  665.  
  666.  
  667. 3.1
  668. log
  669. @Steay version
  670. @
  671. text
  672. @d612 4
  673. a615 1
  674.     
  675. d617 4
  676. @
  677.  
  678.  
  679. 1.2
  680. log
  681. @Before using SpinEvents for global coordination
  682. @
  683. text
  684. @d37 1
  685. a37 1
  686. static SpinLock CpuEnrollLock;
  687. a42 3
  688. //
  689. //    The count of all all current events -- this speeds up exiting
  690. //
  691. a43 1
  692.  
  693. d45 2
  694. a46 2
  695. static int GivingUpCounter;
  696. static int GivingUpGeneration;
  697. d64 1
  698. a68 1
  699.     allocateEventStructures(0);
  700. d71 4
  701. d100 3
  702. a102 1
  703. // Add a single CPU to set of current CPUs
  704. d104 2
  705. d108 21
  706. a128 1
  707.     assert(0);
  708. d138 1
  709. a138 1
  710. CpuMultiplexor::allocateEventStructures(int newIYam)
  711. d140 8
  712. d149 1
  713. a149 1
  714.     sprintf(nameSpace, "[CpuMultiplexor-%d] ", iYam);
  715. d151 3
  716. a153 1
  717.     
  718. d156 1
  719. a156 1
  720.     
  721. d160 20
  722. a179 1
  723.     globalCurrentEventsCounter = &GlobalCurrentEventsCounter;
  724. d183 6
  725. d191 8
  726. d201 2
  727. a202 1
  728.     //    Move remaining events to another queue
  729. d204 1
  730. a204 1
  731.     while ( CurrentEventsCounter[iYam] == 0 ) {
  732. d207 5
  733. a211 3
  734.     CurrentEvents[0] -> add( myCurrentEvents -> remove() );
  735.     CurrentEventsCounter[0]++;
  736.     CurrentEventsCounter[iYam]--;
  737. d214 22
  738. a240 5
  739.  
  740.     GivingUpLock.reserve();
  741.     GivingUpCounter = 0;
  742.     GivingUpGeneration = 1;
  743.     GivingUpLock.release();
  744. d301 1
  745. a301 1
  746.         allocateEventStructures(whoAmI);
  747. d327 1
  748. a340 1
  749.         CpuMultiplexors--;
  750. d367 2
  751. a368 1
  752.     globalCurrentEventsCounter -> add(1);
  753. d374 1
  754. a374 1
  755.     assert( cpu > 0 && cpu < CpuMultiplexors );
  756. d379 2
  757. a416 1
  758.     GlobalCurrentEventsCounter.add(-1);
  759. d424 1
  760. a424 1
  761.     while ( threadToExecute == 0 && GlobalCurrentEventsCounter.add(0) > 0 ) {
  762. d457 20
  763. a476 2
  764.             GlobalCurrentEventsCounter.add(-1);
  765.             CurrentEventsCounter[ask]--;
  766. a480 14
  767.     
  768.     if ( threadToExecute == 0 ) {
  769. #ifndef NDEBUG
  770.         if (CpuMuxDebugFlag) {
  771.         CpuCerrLock.reserve();
  772.         cerr << name();
  773.         cerr << "Did not find anything, may look again";
  774.         cerr << " # of global events = ";
  775.         cerr << GlobalCurrentEventsCounter.add(0);
  776.         cerr << "\n";
  777.         CpuCerrLock.release();
  778.         }
  779. #endif /* NDEBUG */
  780.     }
  781. d488 1
  782. a488 1
  783.         cerr << " nothing\n";
  784. d495 4
  785. d530 1
  786. d532 1
  787. a535 5
  788.         //
  789.         // Ok, we have decided that there is nothing for us to do,
  790.         // and there is nothing for anyone else to do either (maybe).
  791.         // So we need to decide if we are going to advance time or not.
  792.         //
  793. a536 9
  794. #ifndef NDEBUG
  795.         if (CpuMuxDebugFlag) {
  796.         CpuCerrLock.reserve();
  797.         cerr << name();
  798.         cerr << "Did not find anything, maybe rendezvous\n";
  799.         CpuCerrLock.release();
  800.         }
  801. #endif /* NDEBUG */
  802.  
  803. d538 1
  804. a538 1
  805.         oldGeneration = GivingUpGeneration;
  806. d540 6
  807. a545 15
  808.         //
  809.         // If I am here, I have nothing to do. If everyone
  810.         // else is here, they have nothing to do. If I am
  811.         // the last one here, no one has anything to do.
  812.         // Ergo, time to move on.
  813.         //
  814.         if ( GivingUpCounter == CpuMultiplexors ) {
  815. #ifndef NDEBUG
  816.         if (CpuMuxDebugFlag) {
  817.             CpuCerrLock.reserve();
  818.             cerr << name();
  819.             cerr << "advance GivingUp generation count\n";
  820.             CpuCerrLock.release();
  821.         }
  822. #endif /* NDEBUG */
  823. d547 1
  824. a547 1
  825.         GivingUpGeneration++;
  826. d550 9
  827. d562 2
  828. d565 7
  829. a571 27
  830.         }
  831.         
  832.         //
  833.         // Now, wait for either a new generation or a new event
  834.         //
  835.         
  836.         int giveUp = 0;
  837.         
  838.         for (;;) {
  839.         if ( GlobalCurrentEventsCounter.value() > 0 ) {
  840.             //
  841.             // Race condition. Not certain why this occurs, but
  842.             // it does (measured by inserting a print).
  843.             //
  844.             GivingUpLock.reserve();
  845.             if ( oldGeneration != GivingUpGeneration ) {
  846. //            CpuCerrLock.reserve();
  847. //            cerr << name() << "would have crapped out here\n";
  848. //            CpuCerrLock.release();
  849.  
  850.             GivingUpLock.release();
  851.             }
  852.             else {
  853.             GivingUpCounter--;
  854.             GivingUpLock.release();
  855.             break;
  856.             }
  857. d573 3
  858. a575 5
  859.         if (StopCpuMux || oldGeneration != GivingUpGeneration) {
  860.             giveUp = 1;
  861.             break;
  862.         }
  863.  
  864. d577 6
  865. a582 14
  866.         int val = GivingUpCounter;
  867.         int gen = GivingUpGeneration;
  868.         int exitSoon = ( val == 0 && oldGeneration < gen);
  869.         int waitForMore = ( val != 0 && oldGeneration == gen);
  870.  
  871.         if ( ! (exitSoon || waitForMore) ) {
  872.             //
  873.             //    Lock to make certain this is an error
  874.             //
  875.             GivingUpLock.reserve();
  876.             val = GivingUpCounter;
  877.             gen = GivingUpGeneration;
  878.             exitSoon = ( val == 0 && oldGeneration < gen);
  879.             waitForMore = ( val != 0 && oldGeneration == gen);
  880. d584 1
  881. d586 13
  882. a598 19
  883.             
  884.         if ( ! (exitSoon || waitForMore) ) {
  885.             CpuCerrLock.reserve();
  886.             cerr << name() << " exitSoon = " << exitSoon <<"\n";
  887.             cerr << name() << " waitForMore = " << waitForMore <<"\n";
  888.             cerr << name() << " GivingUpCounter.value() = ";
  889.             cerr << val << "\n";
  890.             cerr << name() << " GlobalCurrentEventsCounter.value() = ";
  891.             cerr << GlobalCurrentEventsCounter.value() << "\n";
  892.             cerr << name() << " oldGeneration = ";
  893.             cerr << oldGeneration << "\n";
  894.             cerr << name() << " GivngUpGeneration = ";
  895.             cerr << gen << "\n";
  896.             cerr.flush();
  897.             CpuCerrLock.release();
  898.             assert(exitSoon);
  899.             assert(waitForMore);
  900.         }
  901.  
  902. a599 8
  903.         }
  904.         
  905.         if (giveUp) {
  906. #ifndef NDEBUG
  907.         if (CpuMuxDebugFlag) {
  908.             CpuCerrLock.reserve();
  909.             cerr << name() << " giving up\n";
  910.             CpuCerrLock.release();
  911. a600 2
  912. #endif /* NDEBUG */
  913.         return;
  914. @
  915.  
  916.  
  917. 1.1
  918. log
  919. @Initial revision
  920. @
  921. text
  922. @d47 3
  923. a49 1
  924. static SpinFetchAndOp GivingUpCounter(0);
  925. d150 2
  926. a151 1
  927.     GivingUpCounter.set(0);
  928. d153 1
  929. d381 1
  930. a381 1
  931.         cerr << " cnt = ";
  932. d451 4
  933. a454 2
  934.         int oldGeneration = GivingUpGeneration;
  935.         int givingUpCounterWas = GivingUpCounter.add(1);
  936. d461 1
  937. a461 1
  938.         if (givingUpCounterWas == CpuMultiplexors-1) {
  939. d472 2
  940. a473 1
  941.         GivingUpCounter.set(0);
  942. d476 3
  943. d488 17
  944. a504 2
  945.             GivingUpCounter.add(-1);
  946.             break;
  947. d510 38
  948. @
  949.